package ua.yandex.collections;

public class MyArrayList implements MyList, MyRandomAccess {

    private static final int DEFAULT_CAPACITY = 10;
    private Object[] dynamicArray;
    private int size;

    public MyArrayList() {
        dynamicArray = new Object[DEFAULT_CAPACITY];
        size = 0;
    }

    public MyArrayList(int initialCapacity) {
        dynamicArray = new Object[initialCapacity];
        size = 0;
    }

    public int size() {
        return size;
    }

    private void ensureCapacity(double coefficent) {
        Object[] temp = new Object[(int) (coefficent * dynamicArray.length)];
        System.arraycopy(dynamicArray, 0, temp, 0, size);
        dynamicArray = temp;
    }

    private void ensureCapacity(int newSize) {
        Object[] temp = new Object[newSize];
        System.arraycopy(dynamicArray, 0, temp, 0, size);
        dynamicArray = temp;
    }

    public void add(Object e) {
        if (size >= dynamicArray.length - 1) {
            ensureCapacity(2.0);
        }
        dynamicArray[size] = e;
        size++;
    }

    public void add(int index, Object e) {
        checkOutOfBoundsFoAdd(index);
        if (size >= dynamicArray.length - 1) {
            ensureCapacity(2.0);
        }

        for (int i = size; i > index; i--) {
            dynamicArray[i] = dynamicArray[i - 1];
        }

        dynamicArray[index] = e;
        size++;
    }

    public void addAll(Object[] c) {
        if (c.length + size > dynamicArray.length) {
            ensureCapacity(2 * (c.length + size));
        }

        System.arraycopy(c, 0, dynamicArray, size, c.length);
        size += c.length;
    }

    public void addAll(int index, Object[] c) {
        checkOutOfBoundsFoAdd(index);
        if (c.length + size > dynamicArray.length) {
            MyArrayList.this.ensureCapacity(2 * (c.length + size));
        }

        System.arraycopy(dynamicArray, index, dynamicArray,
                index + c.length - 1, c.length);
        System.arraycopy(c, 0, dynamicArray, index, c.length);
        size += c.length;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public Object[] toArray() {
        Object[] tempArray = new Object[size];
        System.arraycopy(dynamicArray, 0, tempArray, 0, size);
        return tempArray;
    }

    public Object get(int index) {
        checkOutOfBounds(index);
        return dynamicArray[index];
    }

    public Object remove(int index) {
        checkOutOfBounds(index);
        Object temp = dynamicArray[index];
        if (index != size - 1) {
            System.arraycopy(dynamicArray, index + 1, dynamicArray,
                    index, size - index - 1);
        }
        size--;
        return temp;
    }

    public void set(int index, Object e) {
        checkOutOfBounds(index);
        dynamicArray[index] = e;
    }

    public int indexOf(Object o) {
        int result = 0;
        while (result < size && !dynamicArray[result].equals(o)) {
            result++;
            System.out.println(result);
        }

        if (result == size) {
            result = -1;
        }
        return result;
    }

    public void clear() {
        dynamicArray = new Object[DEFAULT_CAPACITY];
        size = 0;
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append('[');
        if (size > 0) {
            for (int i = 0; i < size - 1; i++) {
                stringBuilder.append(dynamicArray[i]);
                stringBuilder.append(',');
                stringBuilder.append(' ');
            }
            stringBuilder.append(dynamicArray[size - 1]);
        }
        stringBuilder.append(']');
        return stringBuilder.toString();
    }

    private void checkOutOfBounds(int index) {
        if (index < 0 || index >= size) {
            String message = String.valueOf(index) + String.valueOf(size);
            throw new IndexOutOfBoundsException(message);
        }
    }

    private void checkOutOfBoundsFoAdd(int index) {
        if (index < 0 || index > size) {
            String message = String.valueOf(index) + String.valueOf(size);
            throw new IndexOutOfBoundsException(message);
        }

    }

}
